#include <errno.h>
#include <linux/mm.h>
#include <linux/sched.h>

#define MAX_SHM_NUM 20
#define MAX_ARG_PAGES 32

typedef unsigned int key_t;

struct shm
{
    int shmid;
    key_t key;
    size_t size;
    unsigned int head_address;
};

struct shm shm_table[MAX_SHM_NUM];
unsigned int current_shm_num = 0;
int next_id = 1;

int sys_shmget(key_t key, size_t size)
{
    int i = 0;
    // 存在直接返回
    for (; i < current_shm_num; i++)
    {
        if (shm_table[i].key == key)
        {
            return shm_table[i].shmid;
        }
    }

    // 大小超过一页报错
    if (size > PAGE_SIZE)
    {
        return -EINVAL;
    }

    // 获取空闲物理页面
    unsigned int tmp = get_free_page();

    if (tmp == -1)
    {
        return -ENOMEM;
    }

    if (current_shm_num < MAX_SHM_NUM)
    {
        shm_table[current_shm_num].key = key;
        shm_table[current_shm_num].shmid = next_id++;
        shm_table[current_shm_num].size = size;
        shm_table[current_shm_num].head_address = tmp;
        return shm_table[current_shm_num++].shmid;
    }
    else
    {
        return -1;
    }

}

void *sys_shmat(int shmid)
{
    int i;
    if (shmid < 0 || shmid > MAX_SHM_NUM)
        return -EINVAL;

    for (i = 0; i < current_shm_num; i++)
    {
        if (shm_table[i].shmid == shmid)
        {
            unsigned int liner_address = get_base(current->ldt[1]) + current->brk;
            current->brk += PAGE_SIZE;

            unsigned int result = put_page(shm_table[i].head_address, liner_address);
            if (!result)
            {
                return -ERROR;
            }
            incr_mem_map(shm_table[i].head_address);   // 重点
            // 这里返回的是逻辑地址才行
            return current->brk - PAGE_SIZE;
        }
    }
    return -EINVAL;
}